<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script>
// async语法糖执行的逻辑：
// 1. 首先babel将其编译为generate函数
// 2. 用一个函数对其进行“加强”，也就是让generate函数按照预期的“节奏”执行.
// 下面我们写一下这个增强函数（也就类似于让generator函数变成一个async函数）
function generatorToAsync(generatorFun) {
    // 返回的“async函数”
    return function () {
        // 思路分析：
        // 1. 首先我们返回的这个函数说白了就是不断的触发generator迭代器的执行，所以第一步先执行generator函数获取迭代器
        // 2. 然后我们的async函数返回值就是一个promise，promise的value为最后return的值，所以函数体的主结构就是return一个new Promise
        // 3. promise构造函数里我们要做什么？自然是不断的触发generator迭代器的next方法，根据done的值等一些条件适时进行resolve
        // 4. 所以我们封装一个next函数，并且在最后触发一下next函数
        // 5. next函数的核心逻辑——触发迭代器的next方法，done为true直接resolve，否则value值为await后面的promise，所以等待promise实例then之后再递归触发next，并且把本次的value值传递下去
        // 执行generator获取迭代器
        const gen = generatorFun.apply(this, arguments);
        // async函数返回一个promise
        return new Promise((resolve, reject) => {
            const next = (tempAwaitResult) => {
                let res = gen.next(tempAwaitResult);
                const { value, done } = res;
                if(done) {
                    resolve(value);
                } else {
                    return Promise.resolve(value).then((val) => next(val));
                }
            }
            next();
        }) 
    }
}

const getData = () => new Promise(resolve => setTimeout(() => resolve("data"), 1000))
function* testG() {
    // await被编译成了yield
    const data = yield getData()
    // const data = yield 123
    console.log('data: ', data);
    const data2 = yield getData()
    console.log('data2: ', data2);
    return 'success'
}
const result = generatorToAsync(testG)();

setTimeout(() => {
    console.log(result);
}, 5000)
</script>
</body>
</html>